Keyword Searching
contents
키워드 검색(Keyword Searching) (또는 어휘 검색, Lexical Search)은 정보 검색(IR) 분야에서 사용되는 가장 기초적인 기술입니다. 초기 구글과 같은 전통적인 검색 엔진, 데이터베이스 쿼리(SQL의 LIKE), 그리고 검색 라이브러리(Lucene/Elasticsearch 등)의 배후에 있는 메커니즘입니다.
핵심은 사용자의 질의(Query)에 포함된 정확한 단어나 변형된 단어를 데이터베이스의 문서와 대조하는 것입니다. AI를 사용하여 의미를 파악하는 "시맨틱 검색(Semantic Search)"과 달리, 키워드 검색은 특정 텍스트 문자열의 통계적 일치 여부에 의존합니다.
다음은 이 기술이 내부적으로 어떻게 작동하는지에 대한 분석입니다.
1. 데이터 구조: 역색인 (Inverted Index) 📖
빠른 키워드 검색의 비결은 사용자가 검색할 때마다 모든 문서를 샅샅이 뒤지는 것이 아닙니다. (그렇게 하면 책에서 이름을 찾기 위해 모든 페이지를 읽는 것처럼 느릴 것입니다.) 대신, 우리는 **역색인(Inverted Index)**이라는 구조를 미리 구축합니다.
역색인을 교과서 맨 뒤에 있는 '색인(Index)' 과 똑같이 생각하시면 됩니다.
- 정방향 색인 (Forward Index): 문서 $\rightarrow$ 단어 (예: "10페이지에 포함된 단어: 사과, 바나나")
- 역방향 색인 (Inverted Index): 단어 $\rightarrow$ 문서 (예: "사과가 발견된 곳: 10페이지, 55페이지")
역색인의 구조
- 사전 (Dictionary / Vocabulary): 모든 문서에서 발견된 유니크한 단어들의 정렬된 목록입니다.
- 포스팅 리스트 (Postings List): 각 단어에 대해, 해당 단어를 포함하고 있는 문서들의 ID 목록입니다.
- 고급: 포스팅 리스트는 종종 단순히 ID뿐만 아니라 위치 정보(Positions)(예: "문서 1, 5번째 단어")도 저장하여 구문 검색(Phrase Searching)(예: "빠른 갈색 여우"를 순서대로 검색)을 가능하게 합니다.
2. 파이프라인: 텍스트 분석 (수집 과정) ⚙️
데이터가 색인에 들어가기 전에, "분석기(Analyzer)" 파이프라인을 거칩니다. 만약 "running"을 검색한다면, 보통 "run"이 포함된 문서도 찾고 싶을 것이기 때문입니다.
1단계: 토큰화 (Tokenization)
긴 텍스트 스트림을 개별 단어(토큰)로 자릅니다.
- 입력:
"The quick brown-fox!" - 출력:
["The", "quick", "brown", "fox"](보통 구두점은 제거됩니다).
2단계: 정규화 (Normalization / Case Folding)
모든 것을 표준 형식(보통 소문자)으로 변환합니다.
- 입력:
["The", "Quick"] - 출력:
["the", "quick"]
3단계: 불용어 제거 (Stop Word Removal)
의미는 거의 없으면서 공간만 차지하는 매우 흔한 단어들을 제거합니다.
- 입력:
["the", "king", "is", "here"] - 출력:
["king", "here"] - 참고: "To be or not to be" 같은 문장은 불용어로만 구성되어 있기 때문에, 최신 엔진들은 불용어를 제거하지 않고 유지하기도 합니다.
4단계: 어간 추출 / 표제어 추출 (Stemming / Lemmatization)
단어의 변형이 매칭되도록 어근(Root) 형태로 줄입니다.
- 어간 추출 (Stemming - 공격적): 뒷부분을 잘라냅니다. "Running", "Runner", "Runs" $\rightarrow$
run. - 표제어 추출 (Lemmatization - 지능적): 사전을 사용합니다. "Better" $\rightarrow$
good.
3. 검색 알고리즘: 불리언 로직 (Boolean Logic) 🔍
apple AND pie를 검색하면, 엔진은 역색인을 조회합니다.
- "apple"에 대한 포스팅 리스트 가져오기:
[Doc1, Doc5, Doc8] - "pie"에 대한 포스팅 리스트 가져오기:
[Doc2, Doc5, Doc9] - 리스트의 교집합(Intersect) 구하기:
[Doc5]
이 과정은 정렬된 정수 리스트를 병합하는 것이기 때문에 매우 빠릅니다.
4. 랭킹 알고리즘: 관련성 점수 계산 📊
만약 1,000개의 문서가 "Apple"이라는 단어를 포함하고 있다면, 어떤 것이 1등이 되어야 할까요? 점수 계산 알고리즘이 필요합니다.
A. 단어 빈도 (Term Frequency, TF)
"이 문서에 그 단어가 얼마나 자주 등장하는가?"
- 문서 A에 "Apple"이 10번 나오고 문서 B에 1번 나온다면, 문서 A가 더 관련성이 높을 것입니다.
B. 역문서 빈도 (Inverse Document Frequency, IDF)
"이 단어가 전체 데이터베이스에서 얼마나 희귀한가?"
- "The Matrix"를 검색할 때, "The"는 문서의 100%에 등장합니다. 쓸모가 없죠. "Matrix"는 0.1%에만 등장합니다. 이것이 중요합니다.
- IDF는 흔한 단어에 페널티를 주고 희귀한 단어에 가산점을 줍니다.
C. BM25 (Best Matching 25)
이것이 업계 표준 랭킹 알고리즘입니다(Elasticsearch, Solr, Lucene에서 사용). TF-IDF의 진화된 버전입니다.
- TF 포화 (Saturation): 일반 TF에서는 단어가 100번 나오면 100배 더 좋다고 봅니다. BM25에서는 이 이득이 "포화"됩니다. 100번 언급된 것이 20번 언급된 것보다 압도적으로 좋지는 않다고 판단합니다.
- 필드 길이 정규화: "computer"란 단어가 짧은 트윗(짧은 문서)에 한 번 나온다면 강력한 신호입니다. 500페이지짜리 책(긴 문서)에 한 번 나온다면 약한 신호입니다. BM25는 이를 보정합니다.
5. 고급 키워드 기법 🧠
N-그램 (N-Grams - 부분 일치용)
"Apple" 안에 있는 "App"을 어떻게 찾을까요?
단어를 $N$ 글자 크기의 슬라이딩 윈도우로 쪼갭니다.
- "Apple"의 트라이그램(Trigrams):
App,ppl,ple. - 이를 통해 엔진은 부분 문자열(substring)을 효율적으로 매칭할 수 있습니다.
퍼지 검색 (Fuzzy Search - 레벤슈타인 거리)
오타를 처리합니다 (예: 사용자가 "Apply"라고 입력).
엔진은 사전에서 질의어와 "편집 거리(Edit Distance)"가 1 또는 2인(예: 1글자만 다름) 토큰을 찾아냅니다.
6. 키워드 검색의 한계 📉
빠르고 신뢰할 수 있지만, 키워드 검색에는 두 가지 치명적인 결함이 있습니다.
- 다의성 (Polysemy - 한 단어, 다른 뜻):
- 검색어: "Jaguar" (재규어)
- 결과: 자동차와 동물이 뒤섞여 나옴. 엔진은 당신이 어떤 것을 의도했는지 모릅니다.
- 동의성 (Synonymy - 다른 단어, 같은 뜻):
- 검색어: "Laptop" (랩탑)
- 문서: "Notebook computer" (노트북 컴퓨터)
- 결과: 매칭 안 됨. 문자열 자체가 다르기 때문에, 동의어 리스트를 수동으로 프로그래밍하지 않는 한 관련 콘텐츠를 찾지 못합니다.
(이 문제를 해결하기 위해 단어를 공간상의 숫자로 표현하는 벡터 검색 / 시맨틱 검색이 등장했습니다.)
요약
키워드 검색의 과정은 다음과 같습니다.
- 텍스트를 표준 토큰으로 분석(Analyzing).
- 역색인(Inverted Index) 구축 (단어 $\rightarrow$ 문서 ID).
- 불리언 로직을 사용하여 매칭되는 문서 찾기.
- BM25 (TF * IDF) 같은 수학 공식으로 순위 매기기.
references